<!--选择题预览模块-->
<template>
  <div class="item-content">
    <div class="content-options">
      <div class="options-title" :style="{ fontSize: adaptiveFontSize(topicFontSize) }">
        <span class="title-required" v-if="required">*</span>
        <span>{{ id }}、{{ desc }}</span>
        <span
          class="multipleChoiceNumber"
          :style="{ fontSize: adaptiveFontSize(contentFontSize) }"
          v-if="selectType === MULTI_SELECT_TYPE"
        >
          (最多选{{ selectMaxNum }}个)
        </span>
      </div>
      <!--主选项-->
      <div>
        <template v-if="selectType === SINGLE_SELECT_TYPE">
          <el-radio-group v-model="selectValue" @change="matchingRules">
            <template #default>
              <el-radio
                :value="list.id"
                v-for="(list, index) in options"
                :disabled="deliveryStatus === EDIT_STATUS || list.disabled"
                :key="index"
                :style="adaptiveContentStyleFontSize"
              >
                {{ list.id }}&nbsp;{{ list.desc }}&nbsp;
                <el-input
                  type="textarea"
                  :rows="1"
                  v-if="list.needReason"
                  v-model="list.input"
                  maxlength="500"
                  :placeholder="selectValue === list.id ? PLACEHOLDER_TEXT : ''"
                  show-word-limit
                  resize="none"
                  :style="{ fontSize: adaptiveFontSize(contentFontSize) }"
                  :disabled="deliveryStatus === EDIT_STATUS || list.disabled || selectValue !== list.id"
                />
              </el-radio>
            </template>
          </el-radio-group>
        </template>
        <template v-else>
          <el-checkbox-group v-model="selectValue" :max="selectMaxNum" @change="matchingRules">
            <template #default>
              <el-checkbox
                :disabled="deliveryStatus === EDIT_STATUS || list.disabled"
                :label="list.id"
                :value="list.id"
                v-for="(list, index) in options"
                :key="index"
                :style="adaptiveContentStyleFontSize"
              >
                {{ list.id }}&nbsp;{{ list.desc }}&nbsp;
                <el-input
                  type="textarea"
                  :rows="1"
                  v-if="list.needReason"
                  v-model="list.input"
                  maxlength="500"
                  :placeholder="selectValue?.includes(list.id) ? PLACEHOLDER_TEXT : ''"
                  show-word-limit
                  resize="none"
                  :style="{ fontSize: adaptiveFontSize(contentFontSize) }"
                  :disabled="deliveryStatus === EDIT_STATUS || list.disabled || !selectValue?.includes(list.id)"
                />
              </el-checkbox>
            </template>
          </el-checkbox-group>
        </template>
      </div>
      <!--子选项-->
      <div class="options-subOptions" v-for="(list, index) in subQuestion" :key="index">
        <div class="subOptions-title">
          <span>{{ id }}.{{ list.id }}、{{ list.desc }}</span>
          <span class="multipleChoiceNumber" v-if="list.selectType !== SINGLE_SELECT_TYPE"
            >(最多选{{ list.selectMaxNum }}个)</span
          >
        </div>
        <div class="subOptions-options">
          <template v-if="list.selectType === SINGLE_SELECT_TYPE">
            <el-radio-group v-model="list.selectValue">
              <el-radio
                :value="list.id"
                v-for="(list, index) in list.options"
                :disabled="deliveryStatus === EDIT_STATUS"
                :key="index"
              >
                {{ list.id }}&nbsp;{{ list.desc }}&nbsp;
              </el-radio>
            </el-radio-group>
          </template>
          <template v-else>
            <el-checkbox-group v-model="list.selectValue" :max="list.selectMaxNum">
              <el-checkbox
                :label="list.id"
                :value="list.id"
                v-for="(list, index) in list.options"
                :key="index"
                :disabled="deliveryStatus === EDIT_STATUS"
              >
                {{ list.id }}&nbsp;{{ list.desc }}&nbsp;
              </el-checkbox>
            </el-checkbox-group>
          </template>
        </div>
      </div>
      <!--答题反馈-->
      <div class="options-textBox" v-if="needFeedback">
        <div class="textBox-title" :style="{ fontSize: adaptiveFontSize(contentFontSize) }">答题反馈</div>
        <el-input
          type="textarea"
          :rows="5"
          maxlength="1000"
          placeholder="请输入内容"
          v-model="feedback"
          :disabled="deliveryStatus === EDIT_STATUS"
          show-word-limit
          resize="none"
          :style="{ fontSize: adaptiveFontSize(contentFontSize) }"
        ></el-input>
      </div>
    </div>
  </div>
</template>

<script setup>
import useSubmitTheVerification from "@/utils/previewTheConfiguration";
import { toRefs, ref } from "vue";
import { useTemplateEditing } from "@/store/modules/templateEditing";
import {
  REQUIRED_TYPE,
  SCALE_CONFIGURATION,
  DEVICE_TYPE,
  PROCESS_TYPE,
  SELECTION_TYPE,
  PLACEHOLDER_TEXT,
  CHOICE_QUESTION_MOBILE_NAME,
} from "@/utils/mockConfiguration/mockConfig";

const { EDIT_STATUS } = PROCESS_TYPE;
const { SINGLE_SELECT_TYPE, MULTI_SELECT_TYPE } = SELECTION_TYPE;
const templateEditing = useTemplateEditing();
const { votingData, optionalQuestionRules, requiredQuestionRules, disabledQuestionRules } = storeToRefs(templateEditing);
const { submitData } = useSubmitTheVerification(); //提交规则校验

const props = defineProps({
  terminalType: {
    type: String,
    required: true,
    default: DEVICE_TYPE.DESKTOP, //DESKTOP:pc端,MOBILE:移动端
  },
  deliveryStatus: {
    type: String,
    required: true,
    default: PROCESS_TYPE.EDIT_STATUS, //EDIT_STATUS:编辑状态,PREVIEW_STATUS:预览状态,DELIVERY_STATUS:下发状态,SUBMISSION_STATUS:提交状态,
  },
});

//模块样式
const cssStyle = defineModel("cssStyle", {
  type: Object,
  required: false,
});

//模块数据
const businessData = defineModel("businessData", {
  type: Object,
  required: false,
});

const { topicFontSize, contentFontSize } = toRefs(cssStyle.value);
const { options, required, desc, id, selectType, selectMaxNum, selectValue, subQuestion, feedback, needFeedback } = toRefs(
  businessData.value,
);

/**
 * 适配字体
 */
const adaptiveFontSize = computed(() => value => `${value * SCALE_CONFIGURATION[props.terminalType]}rem`);

//选择题选择框自适应
const optionSelectFontSize = adaptiveFontSize.value(contentFontSize.value);

/**
 * 选择题选择框自适应
 */
const adaptiveContentStyleFontSize = computed(() => {
  const generateStyle = prefix => {
    const properties = ["font-size", "input-height", "input-width"];
    return Object.fromEntries(properties.map(prop => [`--${prefix}-${prop}`, optionSelectFontSize]));
  };
  const prefixes = ["el-checkbox", "el-radio"];
  return Object.assign({}, ...prefixes.map(prefix => generateStyle(prefix)));
});

/**
 * 禁用选项以及重置填写原因
 * @param options 选项列表
 */
const disableOption = options => {
  options.forEach(list => {
    list.disabled = true;
    list.input = "";
  });
};

/**
 * 处理禁用选项
 * 当为单选时，禁用选项值与当前选项值相同时，重置选项值；禁用选项值与当前选项值不相同时，不做处理。
 * 当为多选时，禁用选项值与当前选项值相同时，从当前选项值中移除该选项值；禁用选项值与当前选项值不相同时，不做处理。
 */
const disabledOptionActions = {
  radio: (businessData, disabledOptionIdsSet) => {
    businessData.selectValue = disabledOptionIdsSet.has(businessData.selectValue) ? "" : businessData.selectValue;
  },
  checkbox: (businessData, disabledOptionIdsSet) => {
    businessData.selectValue = businessData.selectValue.filter(item => !disabledOptionIdsSet.has(item));
  },
};

/**
 * 处理不同模块的整题禁答
 * 当为选择题时，整体禁用，重置选项值和选项禁用状态。
 * 当为简答题时，整体禁用，重置简答题内容。
 */
const disabledQuestionActions = {
  choiceQuestion: businessData => {
    const { options, selectType } = businessData;
    businessData.selectValue = selectType === SINGLE_SELECT_TYPE ? "" : [];
    disableOption(options);
  },
  shortAnswerQuestion: businessData => {
    businessData.disabled = true;
    businessData.content = "";
  },
};

/**
 * 处理禁用选项
 * @param businessData 业务数据
 * @param disabledOptionIds 禁用选项ID列表
 */
const handleDisabledOption = (businessData, disabledOptionIds) => {
  const { options, selectType } = businessData;
  const disabledOptionIdsSet = new Set(disabledOptionIds);

  // 需要禁用和重置填写原因的选项
  const editOption = options.filter(item => disabledOptionIdsSet.has(item.id));
  disableOption(editOption);

  const action = disabledOptionActions[selectType];
  action && action(businessData, disabledOptionIdsSet);
};

/**
 * 处理不同模块的整题禁答
 * @param businessData 业务数据
 * @param moduleId 模块ID
 */
const handleDisabledQuestion = (businessData, moduleId) => {
  const action = disabledQuestionActions[moduleId];
  action && action(businessData);
};

/**
 * 检查是否触发禁答规则
 * @param questionId 选项ID
 * @param questionObjectId 选项对象ID
 * @param optionIds 禁用选项ID数组
 * @param replyId 选项ID
 */
const isDisableRuleTriggered = (questionId, questionObjectId, optionIds, replyId) =>
  questionId === questionObjectId && optionIds.includes(replyId);

/**
 * 收集题目ID
 * 当关联的选项id包含已答题目的选项id，并且题目id等于已答题目的题目id，并且题目数组不包含当前选答题id，则保存题目id
 * @param rules 规则数组
 * @param questionReplys 已答题目
 */
const collectQuestionIds = (rules, questionReplys) => {
  const replyMap = new Map();
  questionReplys.forEach(({ objectId, replyId }) => {
    if (!replyMap.has(objectId)) {
      replyMap.set(objectId, new Set([replyId]));
      return;
    }
    replyMap.get(objectId).add(replyId);
  });
  
  // 遍历 rules，筛选符合条件的 rule
  return rules
    .filter(({ questionId, optionIds }) => {
      const replyIds = replyMap.get(questionId);
      return replyIds && optionIds.some(optionId => replyIds.has(optionId));
    })
    .map(rule => rule.objectId);
};

/**
 * 处理禁答选项
 * @param questionIdAndDisabledOptionIds 选项ID和禁用选项ID的映射
 * @param objectId 选项ID
 * @param disableIds 禁用选项ID数组
 */
const handleDisabledOptions = (questionIdAndDisabledOptionIds, objectId, disableIds) => {
  const optionIds = questionIdAndDisabledOptionIds.get(objectId) ?? [];
  const updatedArray = [...new Set([...optionIds, ...disableIds])];
  questionIdAndDisabledOptionIds.set(objectId, updatedArray);
};

/**
 * 整题禁答
 * @param disabledQuestionIds 整题禁答
 * @param objectId 选项ID
 */
const wholeQuestionIsNotAnswered = (disabledQuestionIds, objectId) => disabledQuestionIds.push(objectId);

/**
 * 简答题初始化
 * @param businessData 简答题业务数据
 */
const initShortAnswerQuestion = businessData => (businessData.disabled = false);

/**
 * 每次选择时重新初始化选择题
 * @param options 选择题选项
 * @param selectType 选择题类型，radio单选，checkbox多选
 * @param selectValue 选择题选项值
 */
const changeChoiceQuestion = ({ options, selectType, selectValue }) => {
  const isMultipleChoice = selectType === MULTI_SELECT_TYPE; //是否多选
  const selectValueSet = isMultipleChoice ? new Set(selectValue) : selectValue;
  options?.forEach(option => {
    const { id } = option;
    option.disabled = false;
    const isSelected = (!isMultipleChoice && selectValue === id) || (isMultipleChoice && selectValueSet.has(id));
    !isSelected && (option.input = "");
  });
};

/**
 * 匹配规则，每次选择时重新初始化选择题
 */
const matchingRules = () => {
  //所有题目初始化
  votingData.value.forEach(item => {
    const { businessData, moduleId } = item;
    const { selectRule } = businessData;
    //初始化必答星号
    businessData.required = selectRule === REQUIRED_TYPE;
    //根据模块类型初始化
    moduleId === CHOICE_QUESTION_MOBILE_NAME ? changeChoiceQuestion(businessData) : initShortAnswerQuestion(businessData);
  });

  const requiredQuestionIds = ref([]); //必答题ID
  const optionalQuestionIds = ref([]); //选答题ID
  const disabledQuestionIds = ref([]); //禁答题ID(整题的禁答)
  const questionIdAndDisabledOptionIds = ref(new Map()); //题目id和禁用选项id数组(单个选项的禁答)
  const { data } = submitData();
  //1、收集所有的已答题目数据。
  const questionReplys = JSON.parse(data); //已答题目

  //2、根据必答题的关联规则和遍历已答题目数据，收集必答题id。requiredQuestionIds
  requiredQuestionIds.value = collectQuestionIds(requiredQuestionRules.value, questionReplys);

  //3、根据选答题的关联规则和已答题目数据，收集选答题id，optionalQuestionIds.
  optionalQuestionIds.value = collectQuestionIds(optionalQuestionRules.value, questionReplys);

  //4、根据禁答题的关联规则和已答题目数据，收集禁答题id，disabledQuestionIds(如果禁用选项为空，则整题禁答，
  //否则就收集对应的禁答选项questionIdAndDisabledOptionIds)，
  questionReplys.forEach(({ objectId: questionObjectId, replyId }) => {
    disabledQuestionRules.value.forEach(({ questionId, objectId, optionIds, disableIds }) => {
      //检查是否触发禁答规则
      if (!isDisableRuleTriggered(questionId, questionObjectId, optionIds, replyId)) {
        return;
      }
      disableIds.length
        ? handleDisabledOptions(questionIdAndDisabledOptionIds.value, objectId, disableIds) // 处理禁答选项
        : wholeQuestionIsNotAnswered(disabledQuestionIds.value, objectId); // 整题禁答
    });
  });

  //题目类型权重：选答>禁答>必答
  //5、过滤禁答题中的选答题Id,保留最终的禁答题id   finalDisabledQuestionIds。
  const optionalSet = new Set(optionalQuestionIds.value);
  const finalDisabledQuestionIds = disabledQuestionIds.value.filter(item => !optionalSet.has(item));

  //6、过滤必答题中的选答题和最终禁答题（finalDisabledQuestionIds）Id，保留最终的必答题ID   finalRequiredQuestionIds
  const finalDisabledSet = new Set(finalDisabledQuestionIds);
  const finalRequiredQuestionIds = requiredQuestionIds.value.filter(
    item => !optionalSet.has(item) && !finalDisabledSet.has(item),
  );

  //7、遍历最终的禁答题id、必答题ID、禁答题选项、改变对应的样式和他们的值。
  const finalRequiredQuestionIdsSet = new Set(finalRequiredQuestionIds);
  const finalDisabledQuestionIdsSet = new Set(finalDisabledQuestionIds);
  const optionalQuestionIdsSet = new Set(optionalQuestionIds.value);

  votingData.value.forEach(({ businessData, moduleId }) => {
    const { id } = businessData;

    // 必答题加星号
    if (finalRequiredQuestionIdsSet.has(id)) {
      businessData.required = true;
    }

    // 禁用整题
    if (finalDisabledQuestionIdsSet.has(id)) {
      businessData.required = false; // 去除必填星号
      handleDisabledQuestion(businessData, moduleId);
    }

    // 禁答部分选项
    const disabledOptionIds = questionIdAndDisabledOptionIds.value.get(id);
    disabledOptionIds && handleDisabledOption(businessData, disabledOptionIds);

    // 选答题去星号
    optionalQuestionIdsSet.has(id) && (businessData.required = false);
  });
};
</script>

<style lang="less" scoped>
//选项题目模块
:deep(.content-options) {
  width: 100%;
  display: flex;
  flex-direction: column;
  row-gap: 30px;
  //多选和单选组
  .el-checkbox-group,
  .el-radio-group {
    display: flex;
    flex-wrap: wrap;
    row-gap: 25px;
    column-gap: 10px;
    align-items: center;
    width: 100%;
    height: 100%;
    //多选和单选选项
    .el-radio,
    .el-checkbox {
      display: flex;
      height: auto;
      align-items: center;
      column-gap: 10px;
      //多选和单选按钮
      .el-checkbox__input,
      .el-radio__input {
        align-self: stretch;
        display: flex;
        align-items: center;
        .el-radio__inner {
          aspect-ratio: 1;
          height: 60%;
        }
        .el-checkbox__inner:after {
          width: 38%;
          height: 68%;
          left: 27%;
        }
      }
      //按钮选中样式
      .is-checked {
        .el-checkbox__inner,
        .el-radio__inner {
          background-color: @buttonColor;
          border-color: @buttonColor;
        }
      }
      //当有文本输入框的时候，选项的宽度为100%
      &:has(.el-textarea) {
        width: 100%;
        display: flex;
        align-items: center;
        .el-radio__label,
        .el-checkbox__label {
          width: 100%;
          //填写原因输入框
          .el-textarea {
            flex: 1;
            .el-textarea__inner {
              padding: 0;
            }
          }
        }
      }
      //多选和单选选项
      .el-checkbox__label,
      .el-radio__label {
        row-gap: 10px;
        line-height: 1.5;
        flex: 1;
        word-wrap: break-word;
        word-break: break-all;
        white-space: pre-wrap;
        overflow-wrap: break-word;
        display: flex;
        align-items: center;
      }
    }
    //选中的时候文字样式
    .is-checked {
      .el-checkbox__label,
      .el-radio__label {
        color: @buttonColor;
      }
    }
  }
  //选择题标题
  .options-title {
    font-size: 28px;
    word-break: break-all;
    white-space: pre-wrap;
    line-height: 1.5;
    //最多选几个
    .multipleChoiceNumber {
      color: #7a7a7a;
      font-size: 18px;
      margin-left: 20px;
    }
    //星号
    .title-required {
      color: @buttonColor;
    }
  }
  //子选项
  .options-subOptions {
    .multipleChoiceNumber {
      color: #7a7a7a;
      font-size: 12px;
      margin-left: 20px;
    }
    .subOptions-title {
      font-size: 18px;
      word-break: break-all;
      white-space: pre-wrap;
    }
  }
  //答题反馈
  .options-textBox {
    .textBox-title {
      font-size: 16px;
      margin-bottom: 10px;
    }
  }
}
</style>
